﻿using System;
using System.Collections.Generic;
using System.Reflection;
using System.Web;
using System.Web.Routing;
using MyAMS.Utility;
using MyAMS.WebServer.Models;
using MyAMS.WebServer.Models.Extensions;

namespace MyAMS.WebServer.Routing
{
    class ArchiveConstraint : IRouteConstraint
    {
        private static readonly string parsedUriRouteValueName = "ParsedUri";
        private static readonly string nodeRouteValueName = "Node";
        private static readonly string archiveRouteValueName = "Archive";
        private static readonly string archiveRouteRoleAreaName = "Archive";
        private static readonly string invalidArchivePropertyErrorMessage = "";//Resource.Get("Error.InvalidArchivePropertyValueFound");

        #region IRouteConstraint Members

        public bool Match(HttpContextBase httpContext, Route route, string parameterName, RouteValueDictionary values, RouteDirection routeDirection)
        {
            bool isSuccessed = false;
            if (values.ContainsKey(parsedUriRouteValueName) && values.ContainsKey(nodeRouteValueName))
            {
                Uri uri = httpContext.Request.Url;
                Uri parsedUri = values[parsedUriRouteValueName] as Uri;
                if (uri.AbsolutePath.Length > parsedUri.AbsolutePath.Length)
                {
                    string pathleft = uri.AbsolutePath.Remove(0, parsedUri.AbsolutePath.Length);
                    if (pathleft[0] == '/')
                    {
                        pathleft = pathleft.Remove(0, 1);
                    }
                    if (pathleft.Length > 0 && pathleft[pathleft.Length - 1] == '/')
                    {
                        pathleft = pathleft.Remove(pathleft.Length - 1, 1);
                    }
                    string[] paths = pathleft.Split('/');
                    Helper.Assert(paths.Length > 0, ""/*Resource.Get("")*/);
                    Node currentNode = values[nodeRouteValueName] as Node;
                    Archive parsedArchive = Parse(currentNode, paths[0]);
                    bool isArchiveParsed = parsedArchive != null;
                    if (isArchiveParsed)
                    {
                        values.Add(archiveRouteValueName, parsedArchive);
                        values[parsedUriRouteValueName] = new Uri(parsedUri.OriginalString + '/' + paths[0]);
                    }
                    if (paths.Length == 1)
                    {
                        isSuccessed = isArchiveParsed;
                    }
                    else
                    {
                        isSuccessed = false;
                    }
                }
            }
            return isSuccessed;
        }

        #endregion

        private static Archive Parse(Node currentNode, string path)
        {
            List<RoutingRole> baseRoles = currentNode.GetRolesWithInheritance(archiveRouteRoleAreaName, currentNode.IsOwned);
            foreach (BaseNode archive in currentNode.Children)
            {
                if (archive is Archive)
                {
                    List<RoutingRole> roles = new List<RoutingRole>(baseRoles);
                    roles.InsertRange(0, archive.GetRoles(archiveRouteRoleAreaName));
                    foreach (RoutingRole role in roles)
                    {
                        if (role.IsDynamicRole())                                     // 判断当前规则是否为动态解析规则
                        {
                            string propertyName = role.Uri.Substring(1, role.Uri.Length - 2);
                            PropertyInfo propertyInfo = archive.GetType().GetProperty(propertyName);
                            if (propertyInfo != null)
                            {
                                object value = propertyInfo.GetValue(archive, null);
                                Helper.Assert(value != null, invalidArchivePropertyErrorMessage);
                                if (String.Compare(path.UrlDecode(), value.ToString(), true) == 0)
                                {
                                    return archive as Archive;                                 // 如果符合规则, 则为成功解析
                                }
                            }
                        }
                        else
                        {
                            if (String.Compare(path.UrlDecode(), role.Uri, true) == 0)
                            {
                                return archive as Archive;                                    // 如果符合规则, 则为成功解析
                            }
                        }
                    }
                }
            }
            return null;
        }
    }
}
